package com.yxinsur.imc.business.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.*;
import java.util.stream.Collectors;

import com.yxinsur.imc.business.domain.ImcOrderRisk;
import com.yxinsur.imc.business.domain.ImcSupplierPersistency;
import com.yxinsur.imc.business.domain.ImcSupplierPersistencyConfig;
import com.yxinsur.imc.business.domain.ImcSupplierPersistencyDetail;
import com.yxinsur.imc.business.enums.*;
import com.yxinsur.imc.business.form.ImcSuppierPersistencyForm;
import com.yxinsur.imc.business.mapper.ImcOrderRiskMapper;
import com.yxinsur.imc.business.mapper.ImcSupplierPersistencyConfigMapper;
import com.yxinsur.imc.business.mapper.ImcSupplierPersistencyDetailMapper;
import com.yxinsur.imc.business.mapper.ImcSupplierPersistencyMapper;
import com.yxinsur.imc.business.service.IImcSupplierPersistencyService;
import com.yxinsur.imc.business.vo.DenominatorOrderVo;
import com.yxinsur.imc.business.vo.ImcSupplierPersistencyVo;
import com.yxinsur.imc.business.vo.PersistencyOrderRiskVo;
import com.yxinsur.imc.common.exception.BusinessException;
import com.yxinsur.imc.common.utils.DateUtils;
import com.yxinsur.imc.common.utils.SecurityUtils;
import com.yxinsur.imc.common.utils.StringUtils;
import com.yxinsur.imc.system.mapper.SysOrgMapper;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

/**
 * 供应商继续率主Service业务层处理
 *
 * @author imc
 * @date 2021-09-23
 */
@Service
public class ImcSupplierPersistencyServiceImpl extends ServiceImpl<ImcSupplierPersistencyMapper, ImcSupplierPersistency> implements IImcSupplierPersistencyService {
    @Autowired
    private ImcSupplierPersistencyMapper imcSupplierPersistencyMapper;

    @Autowired
    private ImcSupplierPersistencyConfigMapper imcSupplierPersistencyConfigMapper;

    @Autowired
    private ImcOrderRiskMapper imcOrderRiskMapper;

    @Autowired
    private ImcSupplierPersistencyDetailMapper imcSupplierPersistencyDetailMapper;

    @Autowired
    private SysOrgMapper sysOrgMapper;

    /**
     * 查询供应商继续率主
     *
     * @param id 供应商继续率主ID
     * @return 供应商继续率主
     */
    @Override
    public ImcSupplierPersistency selectImcSupplierPersistencyById(String id) {
        return imcSupplierPersistencyMapper.selectImcSupplierPersistencyById(id);
    }

    /**
     * 查询供应商继续率主列表
     *
     * @param imcSuppierPersistencyForm 供应商继续率主
     * @return 供应商继续率主
     */
    @Override
    public List<ImcSupplierPersistencyVo> selectImcSupplierPersistencyList(ImcSuppierPersistencyForm imcSuppierPersistencyForm) {
        ImcSupplierPersistency imcSupplierPersistency = new ImcSupplierPersistency();
        BeanUtils.copyProperties(imcSuppierPersistencyForm,imcSupplierPersistency);
        imcSupplierPersistency.setIsDeleted(IsDeletedEnum.N.getCode());
        imcSupplierPersistency.setSupplierId(imcSuppierPersistencyForm.getRepoSupplierId());
        imcSupplierPersistency.setTenantId(SecurityUtils.getTenantId());
        List<ImcSupplierPersistencyVo> persistencyVos = imcSupplierPersistencyMapper.selectImcSupplierPersistencyList(imcSupplierPersistency);
        for (ImcSupplierPersistencyVo persistencyVo : persistencyVos) {
            //获得枚举值
            getEnumCode(persistencyVo);
        }
        return persistencyVos;
    }

    private void getEnumCode(ImcSupplierPersistencyVo persistencyVo) {
        persistencyVo.setPersistencyMethod(PersistencyMethodEnum.getCodeByMethod(persistencyVo.getPersistencyMethod()));
        persistencyVo.setPersistencyDimension(PersistencyDimesionEnum.getCodeByDimesion(persistencyVo.getPersistencyDimension()));
        persistencyVo.setPersistencyPeriodType(PersistencyPeriodEnum.getCodeByPeriod(persistencyVo.getPersistencyPeriodType()));
        //分母
        String denominator = persistencyVo.getDenominator();
        String[] denominatorArr = denominator.split(",");
        String[] denoAfterArr = new String[denominatorArr.length];
        for (int i = 0; i < denominatorArr.length; i++) {
            denoAfterArr[i]= PersistencyRuleEnum.getValueByCode(denominatorArr[i]);
        }
        persistencyVo.setDenominator(StringUtils.join(denoAfterArr,","));
        //分子
        String numerator = persistencyVo.getNumerator();
        String[] numeratorArr = numerator.split(",");
        String[] numeAfterArr = new String[numeratorArr.length];
        for (int i = 0; i < numeratorArr.length; i++) {
            numeAfterArr[i]= PersistencyRuleEnum.getValueByCode(numeratorArr[i]);
        }
        persistencyVo.setNumerator(StringUtils.join(numeAfterArr,","));
        //机构
        String orgIds = persistencyVo.getOrgIds();
        String[] orgIdsArr = orgIds.split(",");
        String[] orgNamesArr = new String[orgIdsArr.length];
        for (int i = 0; i < orgIdsArr.length; i++) {
            orgNamesArr[i] = sysOrgMapper.selectOrgById(Long.valueOf(orgIdsArr[i])).getOrgName();
        }
        persistencyVo.setOrgNames(StringUtils.join(orgNamesArr,","));
    }

    /**
     * 新增供应商继续率主
     *
     * @param imcSupplierPersistency 供应商继续率主
     * @return 结果
     */
    @Override
    public int insertImcSupplierPersistency(ImcSupplierPersistency imcSupplierPersistency) {
        imcSupplierPersistency.setCreateTime(DateUtils.getNowDate());
        return imcSupplierPersistencyMapper.insertImcSupplierPersistency(imcSupplierPersistency);
    }

    /**
     * 修改供应商继续率主
     *
     * @param imcSupplierPersistency 供应商继续率主
     * @return 结果
     */
    @Override
    public int updateImcSupplierPersistency(ImcSupplierPersistency imcSupplierPersistency) {
        imcSupplierPersistency.setUpdateTime(DateUtils.getNowDate());
        return imcSupplierPersistencyMapper.updateImcSupplierPersistency(imcSupplierPersistency);
    }

    /**
     * 批量删除供应商继续率主
     *
     * @param ids 需要删除的供应商继续率主ID
     * @return 结果
     */
    @Override
    public int deleteImcSupplierPersistencyByIds(Long[] ids) {
        int count =0;
        for (Long id : ids) {
            ImcSupplierPersistency imcSupplierPersistency = new ImcSupplierPersistency();
            imcSupplierPersistency.setIsDeleted(IsDeletedEnum.Y.getCode());
            imcSupplierPersistency.setId(id);
            count+= imcSupplierPersistencyMapper.updateById(imcSupplierPersistency);
            QueryWrapper<ImcSupplierPersistencyDetail> wrapper = new QueryWrapper<>();
            wrapper.eq("supplier_persistency_id",id);
            wrapper.eq("tenant_id",SecurityUtils.getTenantId());
            wrapper.eq("is_deleted",IsDeletedEnum.N.getCode());
            List<ImcSupplierPersistencyDetail> imcSupplierPersistencyDetails = imcSupplierPersistencyDetailMapper.selectList(wrapper);
            for (ImcSupplierPersistencyDetail imcSupplierPersistencyDetail : imcSupplierPersistencyDetails) {
                imcSupplierPersistencyDetail.setIsDeleted(IsDeletedEnum.Y.getCode());
                imcSupplierPersistencyDetailMapper.updateById(imcSupplierPersistencyDetail);
            }
        }
        return count;
    }

    /**
     * 删除供应商继续率主信息
     *
     * @param id 供应商继续率主ID
     * @return 结果
     */
    @Override
    public int deleteImcSupplierPersistencyById(String id) {
        return imcSupplierPersistencyMapper.deleteImcSupplierPersistencyById(id);
    }

    /**
     * 计算供应商继续率
     *
     * @param perConfigId
     * @param calculateDate
     * @return
     */
    @Transactional
    @Override
    public int calculate(Long perConfigId, String calculateDate) {
        Long tenantId = SecurityUtils.getTenantId();
        //入参：计算年月，规则表id
        ImcSupplierPersistencyConfig config = imcSupplierPersistencyConfigMapper.selectById(perConfigId);

        HashMap<String, Object> queryDenominatorMap = new HashMap<>();
        HashMap<String, Object> queryNumeratorMap = new HashMap<>();

        //分母查询参数
        createDenominatorRule(calculateDate,config,queryDenominatorMap);

        //分子查询参数
        createNumeratorRule(calculateDate,config,queryNumeratorMap);


        // 查询order_risk表获得分母相关信息
        List<PersistencyOrderRiskVo> denominatorOrderList = imcOrderRiskMapper.selectPerisitencyOrderByQueryMap(queryDenominatorMap,tenantId);
        denominatorOrderList.removeAll(Collections.singleton(null)); //移除null元素
        if(CollectionUtils.isEmpty(denominatorOrderList)){
            //分母为空直接返回
            throw new BusinessException("分母数据为空，请检查配置信息");
        }
        // 查询order_risk表获得分子相关信息
        List<PersistencyOrderRiskVo> numeratorOrderList = imcOrderRiskMapper.selectPerisitencyOrderByQueryMap(queryNumeratorMap,tenantId);
        ImcSupplierPersistency imcSupplierPersistency = new ImcSupplierPersistency();
        imcSupplierPersistency.setSupplierId(config.getRepoSupplierId());
        imcSupplierPersistency.setSupplierPersistencyConfigId(perConfigId);
        imcSupplierPersistency.setCalculateDate(calculateDate);
        imcSupplierPersistency.setCreateId(SecurityUtils.getUsername());
        imcSupplierPersistency.setCreateTime(DateUtils.getNowDate());
        imcSupplierPersistency.setUpdateId(SecurityUtils.getUsername());
        imcSupplierPersistency.setUpdateTime(DateUtils.getNowDate());
        imcSupplierPersistency.setTenantId(SecurityUtils.getTenantId());
        imcSupplierPersistencyMapper.insert(imcSupplierPersistency);

        ImcSupplierPersistencyDetail detail = new ImcSupplierPersistencyDetail();
        if(PersistencyDimesionEnum.ALL.name().equals(config.getPersistencyDimension())){
            detail.setSupplierPersistencyId(imcSupplierPersistency.getId());
            detail.setDenominatorOrderRiskIds(denominatorOrderList.get(0).getOrderRiskId());
            detail.setDenominatorPrem(denominatorOrderList.get(0).getPayablePrem());
            //分子是否为空
            if(CollectionUtils.isEmpty(numeratorOrderList)){
                detail.setNumeratorPrem(new BigDecimal(BigInteger.ZERO));
            }else{
                detail.setNumeratorOrderRiskIds(numeratorOrderList.get(0).getOrderRiskId());
                detail.setNumeratorPrem(numeratorOrderList.get(0).getPaymentPrem());
            }
            detail.setSysPersistency(detail.getNumeratorPrem().divide(detail.getDenominatorPrem()));
            detail.setCreateId(SecurityUtils.getUsername());
            detail.setCreateTime(DateUtils.getNowDate());
            detail.setUpdateId(SecurityUtils.getUsername());
            detail.setUpdateTime(DateUtils.getNowDate());
            detail.setTenantId(SecurityUtils.getTenantId());
            imcSupplierPersistencyDetailMapper.insert(detail);
        }else{//分产品
            ArrayList<ImcSupplierPersistencyDetail> details = new ArrayList<>(denominatorOrderList.size());
            //分母
            for (PersistencyOrderRiskVo persistencyOrderRiskVo : denominatorOrderList) {
                ImcSupplierPersistencyDetail persistencyDetail = new ImcSupplierPersistencyDetail();
                persistencyDetail.setSupplierPersistencyId(imcSupplierPersistency.getId());
                persistencyDetail.setDenominatorOrderRiskIds(persistencyOrderRiskVo.getOrderRiskId());
                persistencyDetail.setRepoInsId(persistencyOrderRiskVo.getRepoInsId());
                persistencyDetail.setRepoInsName(persistencyOrderRiskVo.getRiskName());
                persistencyDetail.setDenominatorPrem(persistencyOrderRiskVo.getPayablePrem());
                details.add(persistencyDetail);
            }
            //分子
            for (ImcSupplierPersistencyDetail imcSupplierPersistencyDetail : details) {

                for (PersistencyOrderRiskVo persistencyOrderRiskVo : numeratorOrderList) {
                    if(imcSupplierPersistencyDetail.getRepoInsId().equals(persistencyOrderRiskVo.getRepoInsId())){
                        imcSupplierPersistencyDetail.setNumeratorOrderRiskIds(persistencyOrderRiskVo.getOrderRiskId());
                        imcSupplierPersistencyDetail.setNumeratorPrem(persistencyOrderRiskVo.getPaymentPrem());
                        imcSupplierPersistencyDetail.setSysPersistency(imcSupplierPersistencyDetail.getNumeratorPrem().divide(imcSupplierPersistencyDetail.getDenominatorPrem()));
                    }

                }
                imcSupplierPersistencyDetail.setCreateId(SecurityUtils.getUsername());
                imcSupplierPersistencyDetail.setUpdateId(SecurityUtils.getUsername());
                imcSupplierPersistencyDetail.setUpdateTime(DateUtils.getNowDate());
                imcSupplierPersistencyDetail.setCreateTime(DateUtils.getNowDate());
                imcSupplierPersistencyDetail.setTenantId(SecurityUtils.getTenantId());

                imcSupplierPersistencyDetailMapper.insert(imcSupplierPersistencyDetail);
            }
        }

        return 1;
    }

    @Override
    public void checkSupplierCalculate(Long perConfigId, String calculateDate) {
        ImcSupplierPersistencyConfig config = imcSupplierPersistencyConfigMapper.selectById(perConfigId);
        Long repoSupplierId = config.getRepoSupplierId();
        QueryWrapper<ImcSupplierPersistency> wrapper = new QueryWrapper<>();
        wrapper.eq("supplier_id",repoSupplierId);
        wrapper.eq("calculate_date",calculateDate);
        wrapper.eq("is_deleted",IsDeletedEnum.N.getCode());
        wrapper.eq("tenant_id",SecurityUtils.getTenantId());
        List<ImcSupplierPersistency> selectList = imcSupplierPersistencyMapper.selectList(wrapper);
        if(!CollectionUtils.isEmpty(selectList)){
            throw new BusinessException("该保险公司在"+calculateDate+"结算月存在继续率数据，请勿重复计算");
        }
    }

    /**
     * 查询继续率主表分母规则的保单详情
     * @param supplierPersistencyId
     * @return
     */
    @Override
    public ArrayList<String> selectDenominatorOrderParam(Long supplierPersistencyId) {
        ImcSupplierPersistency imcSupplierPersistency = imcSupplierPersistencyMapper.selectById(supplierPersistencyId);
        ImcSupplierPersistencyDetail detail = new ImcSupplierPersistencyDetail();
        detail.setSupplierPersistencyId(imcSupplierPersistency.getId());
        List<ImcSupplierPersistencyDetail> detailList = imcSupplierPersistencyDetailMapper.selectImcSupplierPersistencyDetailList(detail);
        //查询保单的参数
        return getOrderVosByDetail(detailList);
    }

    @Override
    public List<DenominatorOrderVo> selectDenominatorOrderList(ArrayList<String> orderRiskIdList) {
        return imcOrderRiskMapper.selectOrderRiskByDeno(orderRiskIdList);
    }

    private ArrayList<String> getOrderVosByDetail(List<ImcSupplierPersistencyDetail> detailList) {
        List<String> orderRiskIdsArr = detailList.stream().map(ImcSupplierPersistencyDetail::getDenominatorOrderRiskIds).collect(Collectors.toList());
        ArrayList<String> orderRiskIdList = new ArrayList<>();
        for (String orderRiskIds : orderRiskIdsArr) {
            String[] orderIdArr = orderRiskIds.split(",");
            List<String> strings = Arrays.asList(orderIdArr);
            orderRiskIdList.addAll(strings);
        }
        return orderRiskIdList;
    }

    //分子查询参数
    private void createNumeratorRule(String calculateDate, ImcSupplierPersistencyConfig config, HashMap<String, Object> queryNumeratorMap) {
        //获得公共数据查询参数
        makePersistencyQueryMap(config,calculateDate,queryNumeratorMap);
        //获得分子查询参数
        String numerator = config.getNumerator();
        String[] numeratorArr = numerator.split(",");

        //被选择的均为不计入计算
        for (String nume : numeratorArr) {
            switch (nume){
                case "A"://退保
                    queryNumeratorMap.put("endCause","B");
                    break;
                case "B"://减额交清
                    queryNumeratorMap.put("reducedStatus","Y");
                    break;
                case "C"://新增附加险
                    queryNumeratorMap.put("isNewAdditional","Y");
                    break;
                case "D"://复效
                    queryNumeratorMap.put("reinstatementDateStatus","Y");
                    break;
                case "E"://已缴费豁免
                    queryNumeratorMap.put("paymentDateStatus","Y");
                    queryNumeratorMap.put("waiverDateStatus","Y");
                    break;
                case "F"://未缴费豁免
                    queryNumeratorMap.put("paymentDateStatus",null);
                    queryNumeratorMap.put("waiverDateStatus","Y");
                    break;
            }
        }
    }

    //分母查询参数
    private void createDenominatorRule(String calculateDate,ImcSupplierPersistencyConfig config, HashMap<String, Object> queryDenominatorMap) {

        //获得公共数据查询参数
        makePersistencyQueryMap(config,calculateDate,queryDenominatorMap);
        //获得分母查询参数
        String denominator = config.getDenominator();
        String[] denominatorArr = denominator.split(",");
        //被选择的均为不计入计算
        for (String deno : denominatorArr) {
            switch (deno){
                case "A":
                    queryDenominatorMap.put("endCause","B");
                    break;
                case "B":
                    queryDenominatorMap.put("reducedStatus","Y");
                    break;
                case "C":
                    queryDenominatorMap.put("isNewAdditional","Y");
                    break;
                case "D":
                    queryDenominatorMap.put("reinstatementDateStatus","Y");
                    break;
                case "E":
                    queryDenominatorMap.put("paymentDateStatus","Y");
                    queryDenominatorMap.put("waiverDateStatus","Y");
                    break;
                case "F":
                    queryDenominatorMap.put("paymentDateStatus",null);
                    queryDenominatorMap.put("waiverDateStatus","Y");
                    break;
            }
        }
    }

    //获得规则起止日期
    private void makePersistencyQueryMap(ImcSupplierPersistencyConfig config, String calculateDate, HashMap<String, Object> queryMap) {
        queryMap.put("orgIds",config.getOrgIds().split(","));
        queryMap.put("repoSupplierId",config.getRepoSupplierId());
        String persistencyMethod = config.getPersistencyMethod();
        String persistencyPeriodType = config.getPersistencyPeriodType();
        calculateDate=calculateDate+"-01";
        if(PersistencyMethodEnum.ROLL.name().equals(persistencyMethod)){//滚动
            switch (persistencyPeriodType){
                case "YEAR":
                    //例： 计算2021年9月 继续率  2020年9月 的1号 为起期   2021年10月1号为止期 >=10月1号  <10月1号
                    Date yearStart = DateUtils.parseDate(DateUtils.getPreCalendar(DateUtils.parseDate(calculateDate), -11));//11个月前
                    Date yearEnd = DateUtils.parseDate(DateUtils.getPreCalendar(DateUtils.parseDate(calculateDate), 1));//+1个月
                    queryMap.put("periodDateStart",yearStart);
                    queryMap.put("periodDateEnd",yearEnd);
                    break;
                case "SEMESTER":
                    Date semesterStart = DateUtils.parseDate(DateUtils.getPreCalendar(DateUtils.parseDate(calculateDate), -5));//5个月前
                    Date semesterEnd = DateUtils.parseDate(DateUtils.getPreCalendar(DateUtils.parseDate(calculateDate), 1));//+1个月
                    queryMap.put("periodDateStart",semesterStart);
                    queryMap.put("periodDateEnd",semesterEnd);
                    break;
                case "QUARTER":
                    Date quarterStart = DateUtils.parseDate(DateUtils.getPreCalendar(DateUtils.parseDate(calculateDate), -2));//2个月前
                    Date quarterEnd = DateUtils.parseDate(DateUtils.getPreCalendar(DateUtils.parseDate(calculateDate), 1));//+1个月
                    queryMap.put("periodDateStart",quarterStart);
                    queryMap.put("periodDateEnd",quarterEnd);
                    break;
                case "MONTH":
                    Date monthEnd = DateUtils.parseDate(DateUtils.getPreCalendar(DateUtils.parseDate(calculateDate), 1));//+1个月
                    queryMap.put("periodDateStart",calculateDate);
                    queryMap.put("periodDateEnd",monthEnd);
                    break;
            }
        }else{//自然
            String year = calculateDate.substring(0, 3);
            switch (persistencyPeriodType){
                case "YEAR":
                    //例： 自然年一整年
                    String yearStart = year+"-01-01";
                    Date yearEnd = DateUtils.parseDate(DateUtils.getPreCalendar(DateUtils.parseDate(yearStart),12));
                    queryMap.put("periodDateStart",yearStart);
                    queryMap.put("periodDateEnd",yearEnd);
                    break;
                case "SEMESTER":
                    //判断是否大于6月30号 大于就是下半年  小于就是上半年
                    Date semesterStart = DateUtils.getHalfYearStartTime(DateUtils.parseDate(calculateDate));//半年开始
                    Date semesterEnd = DateUtils.getHalfYearEndTime(DateUtils.parseDate(calculateDate));//半年结束
                    queryMap.put("periodDateStart",semesterStart);
                    queryMap.put("periodDateEnd",semesterEnd);
                    break;
                case "QUARTER":
                    Date quarterStart = DateUtils.getCurrentQuarterStartTime(DateUtils.parseDate(calculateDate));//2个月前
                    Date quarterEnd = DateUtils.getCurrentQuarterEndTime(DateUtils.parseDate(calculateDate));//+1个月
                    queryMap.put("periodDateStart",quarterStart);
                    queryMap.put("periodDateEnd",quarterEnd);
                    break;
                case "MONTH":
                    Date monthEnd = DateUtils.parseDate(DateUtils.getPreCalendar(DateUtils.parseDate(calculateDate), 1));//+1个月
                    queryMap.put("periodDateStart",calculateDate);
                    queryMap.put("periodDateEnd",monthEnd);
                    break;
            }
        }
        //继续率类型
        String persistencyType = config.getPersistencyType();
        queryMap.put("payYear",PersistencyRateTypeEnum.getYearByKeyName(persistencyType));


        //计算维度
        String persistencyDimension = config.getPersistencyDimension();
        queryMap.put("dimension",persistencyDimension);
    }
}
